<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Triangle with Angles and Copy</title>
    <style>
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <canvas id="myCanvas" width="400" height="400"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        const points = [];
        const triangles = [];
        const radius = 5;
        let dragging = false;
        let rotating = false;
        let startAngle = 0;
        let currentAngle = 0;
        let offsetX, offsetY;
        let activeTriangle = null;

        canvas.addEventListener('click', (event) => {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;

            if (points.length < 3) {
                drawCircle(x, y);
                points.push({x, y});
            }

            if (points.length === 3 && !dragging && !rotating) {
                triangles.push({
                    points: points.map(p => ({...p})),
                    angle: 0
                });
                points.length = 0;
                drawTriangles();
            }

            if (triangles.length > 0) {
                triangles.forEach(triangle => {
                    if (isInsideTriangle(triangle, x, y)) {
                        activeTriangle = triangle;
                    }
                });
            }
        });

        canvas.addEventListener('mousedown', (event) => {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;

            if (triangles.length > 0) {
                if (activeTriangle && isInsideTriangle(activeTriangle, x, y)) {
                    dragging = true;
                    offsetX = x;
                    offsetY = y;
                } else {
                    triangles.forEach(triangle => {
                        if (isInsideTriangle(triangle, x, y)) {
                            activeTriangle = triangle;
                            dragging = true;
                            offsetX = x;
                            offsetY = y;
                        }
                    });
                    if (!activeTriangle) {
                        rotating = true;
                        startAngle = Math.atan2(y - getCentroid(activeTriangle).y, x - getCentroid(activeTriangle).x) - activeTriangle.angle;
                    }
                }
            }
        });

        canvas.addEventListener('mousemove', (event) => {
            if (dragging || rotating) {
                const rect = canvas.getBoundingClientRect();
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;

                if (dragging && activeTriangle) {
                    const dx = x - offsetX;
                    const dy = y - offsetY;
                    offsetX = x;
                    offsetY = y;
                    moveTriangle(activeTriangle, dx, dy);
                }

                if (rotating && activeTriangle) {
                    const angle = Math.atan2(y - getCentroid(activeTriangle).y, x - getCentroid(activeTriangle).x) - startAngle;
                    rotateTriangle(activeTriangle, angle - activeTriangle.angle);
                    activeTriangle.angle = angle;
                }

                drawTriangles();
            }
        });

        canvas.addEventListener('mouseup', () => {
            dragging = false;
            rotating = false;
        });

        function drawCircle(x, y) {
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2, true);
            ctx.fillStyle = 'red';
            ctx.fill();
        }

        function drawTriangles() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            triangles.forEach(triangle => {
                drawTriangle(triangle);
            });
        }

        function drawTriangle(triangle) {
            const { points } = triangle;
            ctx.beginPath();
            ctx.moveTo(points[0].x, points[0].y);
            ctx.lineTo(points[1].x, points[1].y);
            ctx.lineTo(points[2].x, points[2].y);
            ctx.closePath();
            ctx.fillStyle = 'red';
            ctx.fill();
            drawAngles(triangle);
        }

        function isInsideTriangle(triangle, x, y) {
            const [A, B, C] = triangle.points;
            const areaOrig = triangleArea(A, B, C);
            const area1 = triangleArea({x, y}, B, C);
            const area2 = triangleArea(A, {x, y}, C);
            const area3 = triangleArea(A, B, {x, y});
            return Math.abs(areaOrig - (area1 + area2 + area3)) < 0.01;
        }

        function triangleArea(p1, p2, p3) {
            return Math.abs(p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2;
        }

        function getCentroid(triangle) {
            const [A, B, C] = triangle.points;
            return {
                x: (A.x + B.x + C.x) / 3,
                y: (A.y + B.y + C.y) / 3
            };
        }

        function moveTriangle(triangle, dx, dy) {
            triangle.points.forEach(point => {
                point.x += dx;
                point.y += dy;
            });
        }

        function rotateTriangle(triangle, angle) {
            const centroid = getCentroid(triangle);
            triangle.points.forEach(point => {
                const x = point.x - centroid.x;
                const y = point.y - centroid.y;
                const newX = x * Math.cos(angle) - y * Math.sin(angle);
                const newY = x * Math.sin(angle) + y * Math.cos(angle);
                point.x = newX + centroid.x;
                point.y = newY + centroid.y;
            });
        }

        function drawAngles(triangle) {
            const [A, B, C] = triangle.points;
            const angles = calculateAngles(A, B, C);
            drawAngleText(A, angles[0], '∠1');
            drawAngleText(B, angles[1], '∠2');
            drawAngleText(C, angles[2], '∠3');
        }

        function calculateAngles(A, B, C) {
            const angleA = Math.acos((distance(B, C) ** 2 + distance(A, C) ** 2 - distance(A, B) ** 2) / (2 * distance(B, C) * distance(A, C)));
            const angleB = Math.acos((distance(A, C) ** 2 + distance(A, B) ** 2 - distance(B, C) ** 2) / (2 * distance(A, C) * distance(A, B)));
            const angleC = Math.PI - angleA - angleB;
            return [angleA, angleB, angleC].map(angle => angle * (180 / Math.PI)); // 转换为度数
        }

        function distance(p1, p2) {
            return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
        }

        function drawAngleText(point, angle, text) {
            ctx.fillStyle = 'black';
            ctx.font = '12px Arial';
            ctx.fillText(`${text} ${angle.toFixed(1)}°`, point.x + 10, point.y - 10);
        }
    </script>
</body>
</html>
